package com.nulldev.util.web.HttpServer3.extensions.nCaptcha.captchas.shapes;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import com.nulldev.util.VariableAPI.RandomUtil;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.data.Images.ColorUtil;
import com.nulldev.util.data.Images.ImageUtil;
import com.nulldev.util.data.Images.legacy.TextObf;
import com.nulldev.util.data.Images.legacy.TextObf.ObfuscationMethod;
import com.nulldev.util.data.Sets.DataSet;
import com.nulldev.util.gui.swingAPI.Swing;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.Captcha;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3.Request;

public class ShapeIdentification implements Captcha {

	private static final int CANVAS_WIDTH = 320;
	private static final int CANVAS_HEIGHT = 240;

	@Override
	public DataSet<String, String[]> generateBase64Image(final int botLevel, final Request request) {
		final ShapeType shape = ShapeType.random();
		final BufferedImage bf = ImageUtil.createFromColorImg(Color.white, CANVAS_WIDTH, CANVAS_HEIGHT);
		final Graphics g = bf.createGraphics();
		((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, Swing.autoAAHint());
		// Always obfuscate the screen on any bot level.
		g.setColor(ColorUtil.rainbow(200, .4f));
		g.fillRect(0, 0, 80, 240);
		g.setColor(ColorUtil.rainbow(1200, .8f));
		g.fillRect(80, 0, 80, 240);
		g.setColor(ColorUtil.rainbow(2400, .4f));
		g.fillRect(160, 0, 80, 240);
		g.setColor(ColorUtil.rainbow(2800, .2f));
		g.fillRect(240, 0, 80, 240);
		// The transparency trick was removed since it sucked.
		// Also it broke the shapes.
		int _posX = RandomUtil.randInt(5, 250);
		int _posY = RandomUtil.randInt(5, 190);
		if (_posX + 70 > CANVAS_WIDTH)
			_posX -= 70;
		if (_posY + 60 > CANVAS_HEIGHT)
			_posY -= 60;
		final int posX = _posX;
		final int posY = _posY;
		switch (shape) {
			case SQUARE: {
				g.setColor(ColorUtil.randomColor(255));
				g.fillRect(posX, posY, 60, 60);
				break;
			}
			case CIRCLE: {
				g.setColor(ColorUtil.randomColor(255));
				g.fillOval(posX, posY, 70, 70);
				break;
			}
			case ARC: {
				g.setColor(ColorUtil.randomColor(255));
				g.fillArc(posX, posY, 70, 70, 60, 120);
				break;
			}
			case RECTANGLE: {
				g.setColor(ColorUtil.randomColor(RandomUtil.randInt(0, 255)));
				final int width = RandomUtil.randInt(40, 90);
				final int height = RandomUtil.randInt(width + 20, width + 50);
				g.fillRoundRect(posX, posY, width, height, 5, 5);
				break;
			}
			default:
				throw new UnsupportedOperationException("Unknown shape: " + shape);
		}
		// increase bot difficulty.
		for (int in = 0; in < 4; in++) {
			for (int i = 0; i < bf.getWidth() / 2; i++) {
				g.setColor(ColorUtil.randomColor());
				g.drawRect(RandomUtil.randInt(0, bf.getWidth()), RandomUtil.randInt(0, bf.getHeight()), 1, 1);
			}
		}
		final BufferedImage bf2 = TextObf.obfuscateImage(bf, (botLevel > 2 ? ObfuscationMethod.Noise : ObfuscationMethod.RainbowBackgroundPixels));
		final String b64 = ImageUtil.convertImageDataBase64(bf2);
		g.dispose();
		return new DataSet<String, String[]>("data:image/png;base64," + b64, new String[]
			{ shape.text(), shape.text().toUpperCase(), StringsUtil.capitalizeString(shape.text()) });
	}

	@Override
	public String getType() {
		return "shapes";
	}

}
